using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace BinaryFileViewer
{
    public partial class Form1 : Form
    {
        private FileStream m_binaryFile = null;
        private Byte[] m_dataBuffer = new Byte[1024];
        private Int32 m_dataLength = 0;

        public Int32 DataLength
        {
            get { return m_dataLength; }
            set { m_dataLength = value; }
        }

        public Byte[] DataBuffer
        {
            get { return m_dataBuffer; }
            set{ m_dataBuffer = value; }
        }

        public FileStream BinaryFile
        {
            get { return m_binaryFile; }
            set
            {
                cmbPageSize.Enabled = (null != value);
                cmbColumns.Enabled = (null != value);
                m_binaryFile = value;
                this.DataLength = BinaryFile.Read(DataBuffer, 0, DataBuffer.Length);
                this.cmbPageSize.Text = this.DataBuffer.Length.ToString();
                this.cmbColumns.Text = this.binaryViewerCtrl1.Columns.ToString();
                Render();
            }
        }

        public void Render()
        {
            try
            {
                pgBar.Visible = true;
                this.Cursor = Cursors.WaitCursor;
                this.binaryViewerCtrl1.Data = this.DataBuffer;
                lblRange2.Text = (BinaryFile.Position - DataLength).ToString() + " - " + BinaryFile.Position.ToString() + " / " + BinaryFile.Length.ToString();
                btnBack.Enabled = (0 < (BinaryFile.Position - DataLength));
                btnFront.Enabled = (BinaryFile.Position < BinaryFile.Length);
                this.binaryViewerCtrl1.Render(this.DataLength);
                Application.DoEvents();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                this.Cursor = Cursors.Default;
                pgBar.Visible = false;
            }
        }

        public Form1() : this(String.Empty)
        {
        }

        public Form1(String fileName)
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.FileName = String.Empty;
            ofd.Multiselect = false;
            ofd.Filter = "All files|*.*";
            ofd.Filter += "|Archive files|*.zip;*.rar;*.ace;*.tar;*.gz;*.7z;*.jar;*.cab;*.lz";
            ofd.Filter += "|Text files|*.txt;*.log";
            ofd.Filter += "|Image files|*.bmp;*.jpg;*.gif;*.jpeg;*.png;*.tiff;*.pcs;*.psd;*.svg;*.ico";
            ofd.Filter += "|Application files|*.exe;*.com;*.bin;*.obj;*.pdb;*.com;*.dll;*.ocx;*.tlb;*.lib;*.o;*.class;*.resx";
            ofd.Filter += "|Script files|*.js;*.vbs;*.vb;*.cs;*.php;*.py;*.ws;*.rc";
            ofd.Filter += "|Source files|*.c;*.cpp;*.h;*.java;*.html;*.htm;*.jsp";
            ofd.Filter += "|Document, Worksheet|*.docx;*.doc;*.xls;*.xlsx;*.rtf;*.pdf";
            if(DialogResult.OK == ofd.ShowDialog())
            {
                OpenFile(ofd.FileName);
            }
        }

        private void OpenFile(String fileName)
        {
            if(null != BinaryFile)

            {
                BinaryFile.Close();
            }
            this.Text = "Binary File Viewer - " + (new FileInfo(fileName)).Name;
            this.BinaryFile = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            if((null != this.BinaryFile))
            {
                Int64 offset = 0 - (DataLength + DataBuffer.Length);
                if (0 > (BinaryFile.Position + offset))
                {
                    BinaryFile.Seek(0, SeekOrigin.Begin);
                }
                else
                {
                    BinaryFile.Seek(offset, SeekOrigin.Current);
                }
                this.DataLength = BinaryFile.Read(this.DataBuffer, 0, this.DataBuffer.Length);
                Render();
            }
        }

        private void btnFront_Click(object sender, EventArgs e)
        {
            if ((null != this.BinaryFile))
            {
                this.DataLength = BinaryFile.Read(this.DataBuffer, 0, this.DataBuffer.Length);
                Render();
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if(null != BinaryFile)
            {
                BinaryFile.Close();
            }
        }

        private void cmbPageSize_SelectedIndexChanged(object sender, EventArgs e)
        {
            Int32 pageSize = Convert.ToInt32(cmbPageSize.Items[cmbPageSize.SelectedIndex]);
            if (pageSize != DataBuffer.Length)
            {
                BinaryFile.Seek(0 - this.DataLength, SeekOrigin.Current);
                this.DataBuffer = new Byte[pageSize];
                this.DataLength = BinaryFile.Read(DataBuffer, 0, DataBuffer.Length);
                Render();
            }
        }

        private void cmbColumns_SelectedIndexChanged(object sender, EventArgs e)
        {
            Int32 columnWidth = Convert.ToInt32(cmbColumns.Items[cmbColumns.SelectedIndex]);
            if (columnWidth != binaryViewerCtrl1.Columns)
            {
                binaryViewerCtrl1.Columns = Convert.ToByte(columnWidth);
                Render();
            }
        }

        private void binaryViewerCtrl1_ViewProgress(object sender, ViewProgressEventArgs e)
        {
            pgBar.Value = Convert.ToInt32(e.Progress);
            Application.DoEvents();
        }

        private void binaryViewerCtrl1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("FileDrop"))
            {
                e.Effect = DragDropEffects.Copy;
            }
        }

        private void binaryViewerCtrl1_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("FileDrop"))
            {
                e.Effect = DragDropEffects.Copy;
            }
        }

        private void binaryViewerCtrl1_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("FileDrop"))
            {
                String[] files = (String[]) e.Data.GetData("FileDrop");
                if(0 < files.Length)
                {
                    OpenFile(files[0]);
                }
            }
        }
    }
}